package gnssio

import (
	"bufio"
	"dgo/goutils/utils"
	"io"
	"os"
	"time"
)

type CommFileReader struct {
	fileName     string
	file         *os.File
	fr           io.Reader
	blockSize    int
	delay        time.Duration
	interval     time.Duration
	recyle       bool
	listeners    *utils.SafeList
	isTerminated bool
	OnEnd        func(sender *CommFileReader)
}

func NewCommFileReader(fileName string, blockSize int, delay time.Duration, interval time.Duration, recyle bool) *CommFileReader {
	rval := &CommFileReader{
		fileName:  fileName,
		delay:     delay,
		interval:  interval,
		blockSize: blockSize,
		listeners: utils.NewSafeList(),
		recyle:    recyle,
	}
	if rval.blockSize <= 0 {
		rval.blockSize = 1024
	}
	return rval
}

func (this *CommFileReader) innerAction() int {
	if this.file == nil {
		return -1
	}

	if this.fr == nil {
		this.fr = bufio.NewReader(this.file)
	}

	buf := make([]byte, this.blockSize)
	n, err := this.fr.Read(buf)
	if n > 0 {
		this.listeners.ForEach(func(val interface{}) {
			val.(I_CommListener).OnReceive(this, buf, n)
		})
	}
	if err == io.EOF {
		this.fr = nil
		return 1
	}
	if err != nil {
		utils.Log.Err(err)
	}

	return 0

}

// =================================================================
func (this *CommFileReader) Start() {
	defer func() {
		if this.OnEnd != nil {
			this.OnEnd(this)
		}
	}()

	this.isTerminated = false

	f, err := os.Open(this.fileName)
	if err != nil {
		utils.Log.Err(err)
		return
	}
	defer f.Close()
	this.file = f

	if this.delay > 0 {
		time.Sleep(this.delay)
	}

	for !this.isTerminated {
		r := this.innerAction()
		if r == 1 {
			utils.Log.Debug("文件" + this.fileName + "已经读取到尾部")
			if !this.recyle {
				break
			}
		} else if r == -1 {
			time.Sleep(time.Second)
		}

		if this.interval > 0 {
			time.Sleep(this.interval)
		}
	}

}

func (this *CommFileReader) Stop() {
	this.isTerminated = true
}

func (this *CommFileReader) Send(buf []byte, l int) int {
	return 0
}

func (this *CommFileReader) AddListener(event I_CommListener) {
	if this.listeners.Exists(event) {
		utils.Log.Warn("I_CommListener已经存在请勿重复侦听")
		return
	}
	this.listeners.Add(event)
}

func (this *CommFileReader) RemoveListener(event I_CommListener) {
	this.listeners.Remove(event)
}
